//! 端到端集成测试
//!
//! 测试 log4r 核心组件的集成场景

mod common;

use common::TestAppender;
use log4r::formatter::{Formatter, TextFormatter};
use log4r::{Appender, Level, LogEvent};
use std::sync::Arc;
use std::thread;

// ============================================================================
// P0: 核心集成场景
// ============================================================================

/// [P0] 测试完整日志流程：创建事件 → 格式化 → 写入 Appender
#[test]
fn test_full_logging_pipeline() {
    // GIVEN: 日志组件
    let formatter = TextFormatter::new();
    let appender = TestAppender::new();

    // WHEN: 创建并处理日志事件
    let event = LogEvent::new(Level::Info, "my_app::module", "服务启动成功");
    let formatted = formatter.format(&event);
    let _ = appender.write(&event);

    // THEN: 事件被正确处理
    assert!(formatted.contains("[INFO ]"), "格式化输出应包含级别");
    assert!(
        formatted.contains("my_app::module:"),
        "格式化输出应包含 target"
    );
    assert!(formatted.contains("服务启动成功"), "格式化输出应包含消息");
    assert_eq!(appender.count(), 1, "Appender 应收到 1 个事件");
}

/// [P0] 测试 FATAL 级别完整流程
#[test]
fn test_fatal_level_full_pipeline() {
    // GIVEN: 日志组件
    let formatter = TextFormatter::new();
    let appender = TestAppender::new();

    // WHEN: 创建 FATAL 级别事件
    let event = LogEvent::new(Level::Fatal, "critical_module", "系统崩溃");

    // THEN: FATAL 标志正确设置
    assert!(event.is_fatal(), "FATAL 事件应标记为 fatal");
    assert!(event.should_write_to_syslog(), "FATAL 应写入系统日志");

    // AND: 格式化和写入正常
    let formatted = formatter.format(&event);
    assert!(formatted.contains("[FATAL]"), "格式化输出应包含 FATAL");

    let _ = appender.write(&event);
    let events = appender.get_events();
    assert_eq!(events[0].level, Level::Fatal);
}

/// [P0] 测试多级别日志处理
#[test]
fn test_multiple_levels_processing() {
    // GIVEN: 日志组件
    let appender = TestAppender::new();
    let levels = [
        Level::Trace,
        Level::Debug,
        Level::Info,
        Level::Warn,
        Level::Error,
        Level::Fatal,
    ];

    // WHEN: 记录所有级别的日志
    for level in &levels {
        let event = LogEvent::new(*level, "test", format!("{:?} message", level));
        let _ = appender.write(&event);
    }

    // THEN: 所有事件都被记录
    assert_eq!(appender.count(), 6, "应记录 6 个事件");

    // AND: 级别正确
    let events = appender.get_events();
    for (i, level) in levels.iter().enumerate() {
        assert_eq!(events[i].level, *level, "事件 {} 级别应为 {:?}", i, level);
    }
}

// ============================================================================
// P1: 多线程集成测试
// ============================================================================

/// [P1] 测试多线程并发日志记录
#[test]
fn test_concurrent_logging() {
    // GIVEN: 共享的 Appender
    let appender = Arc::new(TestAppender::new());
    let formatter = Arc::new(TextFormatter::new());
    let mut handles = vec![];

    // WHEN: 10 个线程各记录 10 条日志
    for thread_id in 0..10 {
        let appender_clone = Arc::clone(&appender);
        let formatter_clone = Arc::clone(&formatter);

        let handle = thread::spawn(move || {
            for msg_id in 0..10 {
                let target = format!("thread_{}", thread_id);
                let event = LogEvent::new(Level::Info, target, format!("消息 {}", msg_id));
                let _ = formatter_clone.format(&event);
                let _ = appender_clone.write(&event);
            }
        });
        handles.push(handle);
    }

    // 等待所有线程完成
    for handle in handles {
        handle.join().expect("线程应成功完成");
    }

    // THEN: 所有事件都被记录
    assert_eq!(appender.count(), 100, "应记录 100 个事件");
}

/// [P1] 测试 Appender 作为 trait object 的多线程使用
#[test]
fn test_appender_trait_object_concurrent() {
    // GIVEN: Appender 作为 trait object
    let appender: Arc<dyn Appender> = Arc::new(TestAppender::new());
    let mut handles = vec![];

    // WHEN: 多线程写入
    for i in 0..5 {
        let appender_clone = Arc::clone(&appender);
        let handle = thread::spawn(move || {
            let event = LogEvent::new(Level::Info, "test", format!("线程 {} 消息", i));
            appender_clone.write(&event)
        });
        handles.push(handle);
    }

    // THEN: 所有写入成功
    for handle in handles {
        let result = handle.join().expect("线程应成功完成");
        assert!(result.is_ok(), "写入应成功");
    }
}

// ============================================================================
// P1: 配置集成测试
// ============================================================================

/// [P1] 测试配置解析与使用
#[test]
fn test_config_integration() {
    use log4r::config::parse_config;

    // GIVEN: TOML 配置
    let toml = r#"
[log4r]
level = "debug"
app_name = "integration-test"

[log4r.modules]
"my_app::db" = "trace"
"my_app::http" = "warn"
"#;

    // WHEN: 解析配置
    let config = parse_config(toml).expect("配置解析应成功");

    // THEN: 配置值正确
    assert_eq!(config.level, Level::Debug);
    assert_eq!(config.app_name, "integration-test");

    // AND: 模块级别覆盖正确
    let db_level = config.modules.get("my_app::db").expect("db 模块应存在");
    let http_level = config.modules.get("my_app::http").expect("http 模块应存在");
    assert_eq!(*db_level, Level::Trace);
    assert_eq!(*http_level, Level::Warn);

    // AND: 可以用于过滤
    assert!(
        Level::Debug.should_log(config.level),
        "DEBUG 应通过全局过滤"
    );
    assert!(
        !Level::Trace.should_log(config.level),
        "TRACE 不应通过全局过滤"
    );
    assert!(
        Level::Trace.should_log(*db_level),
        "TRACE 应通过 db 模块过滤"
    );
}

/// [P1] 测试默认配置集成
#[test]
fn test_default_config_integration() {
    use log4r::config::Log4rConfig;

    // GIVEN: 默认配置
    let config = Log4rConfig::default();

    // WHEN: 使用默认配置过滤
    let filter = config.level;

    // THEN: 默认级别为 INFO
    assert_eq!(filter, Level::Info);
    assert!(!Level::Debug.should_log(filter), "DEBUG 不应通过默认过滤");
    assert!(Level::Info.should_log(filter), "INFO 应通过默认过滤");
}

// ============================================================================
// P2: 边界条件集成测试
// ============================================================================

/// [P2] 测试空消息处理
#[test]
fn test_empty_message_handling() {
    // GIVEN: 空消息事件
    let formatter = TextFormatter::new();
    let appender = TestAppender::new();
    let event = LogEvent::new(Level::Info, "test", "");

    // WHEN: 格式化和写入
    let formatted = formatter.format(&event);
    let _ = appender.write(&event);

    // THEN: 正常处理
    assert!(formatted.contains("[INFO ]"));
    assert_eq!(appender.count(), 1);
}

/// [P2] 测试超长消息处理
#[test]
fn test_long_message_handling() {
    // GIVEN: 超长消息
    let long_message = "A".repeat(10000);
    let formatter = TextFormatter::new();
    let appender = TestAppender::new();
    let event = LogEvent::new(Level::Info, "test", long_message.clone());

    // WHEN: 格式化和写入
    let formatted = formatter.format(&event);
    let _ = appender.write(&event);

    // THEN: 消息完整保留
    assert!(formatted.contains(&long_message));
    let events = appender.get_events();
    assert_eq!(events[0].message, long_message);
}

/// [P2] 测试 Unicode 消息处理
#[test]
fn test_unicode_message_handling() {
    // GIVEN: Unicode 消息
    let unicode_message = "日志消息 🚀 émoji テスト العربية";
    let formatter = TextFormatter::new();
    let appender = TestAppender::new();
    let event = LogEvent::new(Level::Info, "unicode_test", unicode_message);

    // WHEN: 格式化和写入
    let formatted = formatter.format(&event);
    let _ = appender.write(&event);

    // THEN: Unicode 正确处理
    assert!(formatted.contains(unicode_message));
    let events = appender.get_events();
    assert_eq!(events[0].message, unicode_message);
}

/// [P2] 测试特殊字符 target 处理
#[test]
fn test_special_target_handling() {
    // GIVEN: 包含特殊字符的 target
    let special_target = "my_app::模块::sub-module";
    let formatter = TextFormatter::new();
    let event = LogEvent::new(Level::Info, special_target, "test");

    // WHEN: 格式化
    let formatted = formatter.format(&event);

    // THEN: target 正确显示
    assert!(
        formatted.contains(special_target),
        "格式化输出应包含特殊 target"
    );
}

// ============================================================================
// P1: 错误处理集成测试
// ============================================================================

/// [P1] 测试 Appender 错误不影响其他操作
#[test]
fn test_appender_error_isolation() {
    use log4r::Log4rError;

    // GIVEN: 一个会失败的 Appender
    struct FailingAppender;

    impl Appender for FailingAppender {
        fn write(&self, _event: &LogEvent) -> Result<(), Log4rError> {
            Err(Log4rError::appender("FailingAppender", "模拟失败"))
        }
        fn flush(&self) -> Result<(), Log4rError> {
            Ok(())
        }
        fn close(&self) -> Result<(), Log4rError> {
            Ok(())
        }
    }

    // WHEN: 写入失败
    let appender = FailingAppender;
    let event = LogEvent::new(Level::Info, "test", "test");
    let result = appender.write(&event);

    // THEN: 返回错误但不 panic
    assert!(result.is_err());
    let err = result.unwrap_err();
    assert!(err.to_string().contains("FailingAppender"));
}

/// [P1] 测试配置错误处理
#[test]
fn test_config_error_handling() {
    use log4r::config::parse_config;

    // GIVEN: 无效配置
    let invalid_configs = vec![
        "[log4r\nlevel = \"info\"",     // 语法错误
        "[log4r]\nlevel = \"invalid\"", // 无效级别
        "[log4r]\napp_name = 123",      // 类型错误
    ];

    // WHEN/THEN: 所有无效配置都返回错误
    for config in invalid_configs {
        let result = parse_config(config);
        assert!(result.is_err(), "无效配置应返回错误: {}", config);
    }
}
